"""
视图定义
包含了所有API的处理逻辑
"""
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from rest_framework import viewsets, permissions, status, filters, generics
from rest_framework.decorators import action
from rest_framework.generics import ListAPIView
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
from django.contrib.auth import authenticate, login, logout
from django.db import models
from django.utils import timezone
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.views import APIView

from .models import User, Category, Novel, Chapter, Bookshelf, AuthorApplication
from .serializers import (
    UserSerializer, CategorySerializer, NovelSerializer, NovelDetailSerializer,
    ChapterSerializer, BookshelfSerializer, AuthorApplicationSerializer, LoginSerializer, NovelStatusSerializer,
    NovelCreateSerializer
)
from .permissions import IsAuthorOrAdmin, IsNovelAuthorOrAdmin, IsOwnerOrReadOnly, IsAuthorOwner
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth import authenticate, login, logout, update_session_auth_hash
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.utils import timezone
from django.db.models import Q, Count
from django.core.paginator import Paginator
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.http import require_POST

from .models import User, Category, Novel, Chapter, Bookshelf, AuthorApplication


class UserViewSet(viewsets.ModelViewSet):
    """
    用户相关API
    提供用户注册、登录、个人资料管理等功能
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer
    filter_backends = [filters.SearchFilter]
    search_fields = ['username', 'email']

    def get_permissions(self):
        """根据不同的操作设置不同的权限"""
        if self.action in ['create', 'login']:
            # 注册和登录不需要认证
            permission_classes = [permissions.AllowAny]
        elif self.action in ['update', 'partial_update', 'retrieve', 'profile', 'apply_author']:
            # 更新、查看个人资料需要登录
            permission_classes = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
        else:
            # 其他操作需要管理员权限
            permission_classes = [permissions.IsAdminUser]
        return [permission() for permission in permission_classes]

    @action(detail=False, methods=['post'])
    def login(self, request):
        """用户登录"""
        serializer = LoginSerializer(data=request.data)
        if serializer.is_valid():
            username = serializer.validated_data['username']
            password = serializer.validated_data['password']
            user = authenticate(username=username, password=password)

            if user:
                login(request, user)
                return Response({
                    'user': UserSerializer(user).data,
                    'message': '登录成功'
                })
            return Response({'detail': '用户名或密码错误'}, status=status.HTTP_400_BAD_REQUEST)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    @action(detail=False, methods=['post'])
    def logout(self, request):
        """用户登出"""
        logout(request)
        return Response({'detail': '登出成功'})

    @action(detail=False, methods=['get'])
    def profile(self, request):
        """获取当前登录用户信息"""
        serializer = self.get_serializer(request.user)
        return Response(serializer.data)

    @action(detail=False, methods=['post'])
    def apply_author(self, request):
        """申请成为作者"""
        if request.user.role != 'reader':
            return Response({"detail": "只有读者用户可以申请成为作者"}, status=status.HTTP_400_BAD_REQUEST)

        # 检查是否已有待审核的申请
        if AuthorApplication.objects.filter(user=request.user, status='pending').exists():
            return Response({"detail": "您已有一个待审核的申请"}, status=status.HTTP_400_BAD_REQUEST)

        reason = request.data.get('reason', '')
        if not reason:
            return Response({"detail": "申请理由不能为空"}, status=status.HTTP_400_BAD_REQUEST)

        # 创建申请
        AuthorApplication.objects.create(
            user=request.user,
            reason=reason,
            status='pending'
        )

        return Response({"detail": "申请已提交，请等待管理员审核"}, status=status.HTTP_201_CREATED)


class CategoryViewSet(viewsets.ModelViewSet):
    """
    分类管理API
    提供分类的增删改查功能
    """
    queryset = Category.objects.all()
    serializer_class = CategorySerializer

    def get_permissions(self):
        """根据不同的操作设置不同的权限"""
        if self.action in ['list', 'retrieve']:
            # 查看分类不需要特殊权限
            permission_classes = [permissions.IsAuthenticated]
        else:
            # 增删改需要管理员权限
            permission_classes = [permissions.IsAdminUser]
        return [permission() for permission in permission_classes]


class NovelViewSet(viewsets.ModelViewSet):
    """
    小说相关API
    提供小说的增删改查、搜索功能
    """
    serializer_class = NovelSerializer
    permission_classes = [permissions.IsAuthenticated, IsAuthorOrAdmin]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ['category', 'status']
    search_fields = ['title', 'description', 'author__username']
    ordering_fields = ['created_at', 'updated_at']
    queryset = Novel.objects.all()
    serializer_class = NovelSerializer
    permission_classes = [IsAuthorOrAdmin]

    def get_queryset(self):
        """
        根据用户角色和小说状态过滤查询集
        """
        user = self.request.user

        # 管理员可以看到所有小说
        if user.is_staff or user.role == 'admin':
            return Novel.objects.all()

        # 作者可以看到自己的所有小说（包括审核中的）和其他已通过的小说
        elif user.role == 'author':
            return Novel.objects.filter(
                models.Q(author=user) | models.Q(status='approved')
            )

        # 读者只能看到已通过审核的小说
        else:
            return Novel.objects.filter(status='approved')

    def get_permissions(self):
        """根据不同的操作设置不同的权限"""
        if self.action in ['list', 'retrieve', 'search']:
            # 查看和搜索小说不需要特殊权限
            permission_classes = [permissions.IsAuthenticated]
        elif self.action in ['create', 'update', 'partial_update']:
            # 创建和修改小说需要作者或管理员权限
            permission_classes = [IsAuthorOrAdmin]
        elif self.action in ['destroy']:
            # 删除小说需要管理员权限
            permission_classes = [permissions.IsAdminUser]
        else:
            # 其他操作需要认证
            permission_classes = [permissions.IsAuthenticated]
        return [permission() for permission in permission_classes]

    def get_serializer_class(self):
        """根据不同的操作返回不同的序列化器"""
        if self.action == 'retrieve':
            # 获取小说详情时返回带有章节信息的序列化器
            return NovelDetailSerializer
        return NovelSerializer

    def perform_create(self, serializer):
        """创建小说时自动设置作者为当前用户"""
        serializer.save(author=self.request.user, status='pending')

    @action(detail=False, methods=['get'])
    def search(self, request):
        """搜索小说"""
        query = request.query_params.get('q', '')
        category_id = request.query_params.get('category', None)

        queryset = self.get_queryset()

        if query:
            queryset = queryset.filter(title__icontains=query)

        if category_id:
            queryset = queryset.filter(category_id=category_id)

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

    @action(detail=True, methods=['get'])
    def chapters(self, request, pk=None):
        """获取小说的所有章节"""
        novel = self.get_object()
        chapters = novel.chapters.all().order_by('order')
        serializer = ChapterSerializer(chapters, many=True)
        return Response(serializer.data)

    @action(detail=True, methods=['post'])
    def submit(self, request, pk=None):
        """提交审核（作者专用）"""
        novel = self.get_object()
        if novel.author != request.user:
            return Response({"error": "无权操作"}, status=status.HTTP_403_FORBIDDEN)

        novel.status = 'pending'
        novel.save()
        return Response({"status": "已提交审核"})


class ChapterViewSet(viewsets.ModelViewSet):
    """
    小说章节相关API
    提供章节的增删改查、阅读功能
    """
    serializer_class = ChapterSerializer

    def get_queryset(self):
        """根据用户角色和小说状态过滤查询集"""
        user = self.request.user

        # 管理员可以看到所有章节
        if user.is_staff or user.role == 'admin':
            return Chapter.objects.all()

        # 作者可以看到自己小说的所有章节和其他已通过小说的章节
        elif user.role == 'author':
            return Chapter.objects.filter(
                models.Q(novel__author=user) | models.Q(novel__status='approved')
            )

        # 读者只能看到已通过审核的小说章节
        else:
            return Chapter.objects.filter(novel__status='approved')

    def get_permissions(self):
        """根据不同的操作设置不同的权限"""
        if self.action in ['list', 'retrieve', 'read']:
            # 查看和阅读章节不需要特殊权限
            permission_classes = [permissions.IsAuthenticated]
        elif self.action in ['create', 'update', 'partial_update']:
            # 创建和修改章节需要小说作者或管理员权限
            permission_classes = [IsNovelAuthorOrAdmin]
        elif self.action in ['destroy']:
            # 删除章节需要管理员权限
            permission_classes = [permissions.IsAdminUser]
        else:
            # 其他操作需要认证
            permission_classes = [permissions.IsAuthenticated]
        return [permission() for permission in permission_classes]

    @action(detail=True, methods=['post'])
    def read(self, request, pk=None):
        """记录用户阅读章节，更新书架记录"""
        chapter = self.get_object()
        novel = chapter.novel

        # 检查或创建书架记录
        bookshelf, created = Bookshelf.objects.get_or_create(
            user=request.user,
            novel=novel,
            defaults={'last_read_chapter': chapter}
        )

        if not created:
            bookshelf.last_read_chapter = chapter
            bookshelf.save()

        return Response({"detail": "阅读记录已更新"})


class BookshelfViewSet(viewsets.ModelViewSet):
    """
    用户书架相关API
    提供书架的增删改查功能
    """
    serializer_class = BookshelfSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        """只返回当前用户的书架"""
        return Bookshelf.objects.filter(user=self.request.user)

    def perform_create(self, serializer):
        """创建书架记录时自动设置用户为当前用户"""
        serializer.save(user=self.request.user)

    @action(detail=False, methods=['post'])
    def add_to_bookshelf(self, request):
        """添加小说到书架"""
        novel_id = request.data.get('novel_id')
        if not novel_id:
            return Response({"detail": "小说ID不能为空"}, status=status.HTTP_400_BAD_REQUEST)

        try:
            novel = Novel.objects.get(id=novel_id, status='approved')
        except Novel.DoesNotExist:
            return Response({"detail": "小说不存在或未通过审核"}, status=status.HTTP_404_NOT_FOUND)

        bookshelf, created = Bookshelf.objects.get_or_create(
            user=request.user,
            novel=novel
        )

        if created:
            return Response({"detail": "已添加到书架"}, status=status.HTTP_201_CREATED)
        else:
            return Response({"detail": "该小说已在书架中"}, status=status.HTTP_200_OK)

    @action(detail=False, methods=['post'])
    def remove_from_bookshelf(self, request):
        """从书架中移除小说"""
        novel_id = request.data.get('novel_id')
        if not novel_id:
            return Response({"detail": "小说ID不能为空"}, status=status.HTTP_400_BAD_REQUEST)

        try:
            bookshelf = Bookshelf.objects.get(user=request.user, novel_id=novel_id)
            bookshelf.delete()
            return Response({"detail": "已从书架中移除"}, status=status.HTTP_200_OK)
        except Bookshelf.DoesNotExist:
            return Response({"detail": "该小说不在书架中"}, status=status.HTTP_404_NOT_FOUND)


class AdminViewSet(viewsets.ViewSet):
    """
    管理员相关API
    提供管理员审核功能
    """
    permission_classes = [permissions.IsAdminUser]

    @action(detail=False, methods=['get'])
    def pending_author_applications(self, request):
        """获取待审核的作者申请"""
        applications = AuthorApplication.objects.filter(status='pending')
        serializer = AuthorApplicationSerializer(applications, many=True)
        return Response(serializer.data)

    @action(detail=True, methods=['post'])
    def process_author_application(self, request, pk=None):
        """处理作者申请"""
        try:
            application = AuthorApplication.objects.get(pk=pk, status='pending')
        except AuthorApplication.DoesNotExist:
            return Response({"detail": "申请不存在或已处理"}, status=status.HTTP_404_NOT_FOUND)

        action = request.data.get('action')
        if action not in ['approve', 'reject']:
            return Response({"detail": "操作类型无效，必须是 'approve' 或 'reject'"},
                            status=status.HTTP_400_BAD_REQUEST)

        admin_notes = request.data.get('admin_notes', '')

        if action == 'approve':
            # 更新用户角色
            user = application.user
            user.role = 'author'
            user.save()

            # 更新申请状态
            application.status = 'approved'
            application.processed_at = timezone.now()
            application.admin_notes = admin_notes
            application.save()

            return Response({"detail": "已批准用户成为作者"})
        else:
            # 拒绝申请
            application.status = 'rejected'
            application.processed_at = timezone.now()
            application.admin_notes = admin_notes
            application.save()

            return Response({"detail": "已拒绝作者申请"})

    @action(detail=False, methods=['get'])
    def pending_novels(self, request):
        """获取待审核的小说"""
        novels = Novel.objects.filter(status='pending')
        serializer = NovelDetailSerializer(novels, many=True)
        return Response(serializer.data)

    @action(detail=True, methods=['post'])
    def process_novel(self, request, pk=None):
        """审核小说"""
        try:
            novel = Novel.objects.get(pk=pk, status='pending')
        except Novel.DoesNotExist:
            return Response({"detail": "小说不存在或已审核"}, status=status.HTTP_404_NOT_FOUND)

        action = request.data.get('action')
        if action not in ['approve', 'reject']:
            return Response({"detail": "操作类型无效，必须是 'approve' 或 'reject'"},
                            status=status.HTTP_400_BAD_REQUEST)

        feedback = request.data.get('feedback', '')

        if action == 'approve':
            novel.status = 'approved'
            novel.save()

            # 可以添加通知作者的逻辑

            return Response({"detail": "小说已通过审核并发布"})
        else:
            novel.status = 'rejected'
            novel.save()

            # 可以添加通知作者的逻辑，包含反馈信息

            return Response({"detail": "小说审核未通过"})

    @action(detail=False, methods=['get'])
    def category_management(self, request):
        """获取所有分类"""
        categories = Category.objects.all()
        serializer = CategorySerializer(categories, many=True)
        return Response(serializer.data)

    @action(detail=False, methods=['post'])
    def create_category(self, request):
        """创建新分类"""
        name = request.data.get('name')
        if not name:
            return Response({"detail": "分类名称不能为空"}, status=status.HTTP_400_BAD_REQUEST)

        if Category.objects.filter(name=name).exists():
            return Response({"detail": "该分类已存在"}, status=status.HTTP_400_BAD_REQUEST)

        category = Category.objects.create(name=name)
        serializer = CategorySerializer(category)
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    @action(detail=True, methods=['put'])
    def update_category(self, request, pk=None):
        """更新分类"""
        try:
            category = Category.objects.get(pk=pk)
        except Category.DoesNotExist:
            return Response({"detail": "分类不存在"}, status=status.HTTP_404_NOT_FOUND)

        name = request.data.get('name')
        if not name:
            return Response({"detail": "分类名称不能为空"}, status=status.HTTP_400_BAD_REQUEST)

        if Category.objects.filter(name=name).exclude(pk=pk).exists():
            return Response({"detail": "该分类名称已被使用"}, status=status.HTTP_400_BAD_REQUEST)

        category.name = name
        category.save()

        serializer = CategorySerializer(category)
        return Response(serializer.data)

    @action(detail=True, methods=['delete'])
    def delete_category(self, request, pk=None):
        """删除分类"""
        try:
            category = Category.objects.get(pk=pk)
        except Category.DoesNotExist:
            return Response({"detail": "分类不存在"}, status=status.HTTP_404_NOT_FOUND)

        # 检查是否有小说使用该分类
        if Novel.objects.filter(category=category).exists():
            return Response({"detail": "该分类下有小说，无法删除"}, status=status.HTTP_400_BAD_REQUEST)

        category.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

    @action(detail=False, methods=['get'])
    def system_stats(self, request):
        """获取系统统计信息"""
        total_users = User.objects.count()
        readers = User.objects.filter(role='reader').count()
        authors = User.objects.filter(role='author').count()

        total_novels = Novel.objects.count()
        approved_novels = Novel.objects.filter(status='approved').count()
        pending_novels = Novel.objects.filter(status='pending').count()

        total_chapters = Chapter.objects.count()

        pending_author_applications = AuthorApplication.objects.filter(status='pending').count()

        stats = {
            'users': {
                'total': total_users,
                'readers': readers,
                'authors': authors,
            },
            'novels': {
                'total': total_novels,
                'approved': approved_novels,
                'pending': pending_novels,
            },
            'chapters': {
                'total': total_chapters,
            },
            'pending_reviews': {
                'author_applications': pending_author_applications,
                'novels': pending_novels,
            }
        }

        return Response(stats)


# 基本视图
def frontend_home(request):
    """首页视图"""
    # 获取推荐小说
    recommended_novels = Novel.objects.filter(status='approved').order_by('-created_at')[:6]

    # 获取分类列表
    categories = Category.objects.all()

    # 获取最新小说
    latest_novels = Novel.objects.filter(status='approved').order_by('-created_at')[:10]

    # 获取热门小说（按照书架收藏数）
    popular_novels = Novel.objects.filter(status='approved').annotate(
        bookshelf_count=Count('in_bookshelves')
    ).order_by('-bookshelf_count')[:10]

    context = {
        'recommended_novels': recommended_novels,
        'categories': categories,
        'latest_novels': latest_novels,
        'popular_novels': popular_novels
    }

    return render(request, 'novel/home.html', context)


@csrf_protect
def custom_login(request):
    """自定义登录视图，根据用户角色重定向"""
    if request.user.is_authenticated:
        return redirect('frontend_home')

    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        remember = request.POST.get('remember', False)

        user = authenticate(request, username=username, password=password)

        if user is not None:
            login(request, user)

            # 如果选择了"记住我"，设置会话过期时间为2周
            if remember:
                request.session.set_expiry(1209600)  # 2周 = 1209600秒
            else:
                request.session.set_expiry(0)  # 关闭浏览器后过期

            # 根据用户角色重定向
            if user.is_staff or user.role == 'admin':
                # 管理员重定向到Django Admin
                return redirect('admin:index')
            else:
                # 普通用户重定向到前端首页
                return redirect('frontend_home')
        else:
            messages.error(request, '用户名或密码错误')

    return render(request, 'novel/login.html')


def custom_logout(request):
    """用户登出视图"""
    logout(request)
    return redirect('frontend_home')


@csrf_protect
def register(request):
    """用户注册视图"""
    if request.user.is_authenticated:
        return redirect('frontend_home')

    if request.method == 'POST':
        username = request.POST.get('username')
        email = request.POST.get('email')
        password = request.POST.get('password')
        confirm_password = request.POST.get('confirm_password')
        agree_terms = request.POST.get('agree_terms', False)

        # 验证
        if not agree_terms:
            messages.error(request, '请阅读并同意用户协议和隐私政策')
            return render(request, 'novel/register.html')

        if password != confirm_password:
            messages.error(request, '两次输入的密码不一致')
            return render(request, 'novel/register.html')

        if User.objects.filter(username=username).exists():
            messages.error(request, '用户名已存在')
            return render(request, 'novel/register.html')

        if User.objects.filter(email=email).exists():
            messages.error(request, '邮箱已被注册')
            return render(request, 'novel/register.html')

        # 创建用户
        user = User.objects.create_user(
            username=username,
            email=email,
            password=password,
            role='reader'  # 默认为读者角色
        )

        # 自动登录
        login(request, user)

        messages.success(request, '注册成功！欢迎加入畅读小说网')
        return redirect('frontend_home')

    return render(request, 'novel/register.html')


# 用户中心视图
@login_required
def user_profile(request):
    """用户个人中心"""
    user = request.user

    # 获取用户书架中的小说数量
    bookshelf_count = Bookshelf.objects.filter(user=user).count()

    # 如果是作者，获取创作的小说数量
    novel_count = 0
    if user.role == 'author':
        novel_count = Novel.objects.filter(author=user).count()

    # 计算注册天数
    days_registered = (timezone.now().date() - user.date_joined.date()).days

    if request.method == 'POST':
        # 处理表单提交
        email = request.POST.get('email')
        bio = request.POST.get('bio', '')

        # 验证邮箱是否被其他用户使用
        if User.objects.filter(email=email).exclude(id=user.id).exists():
            messages.error(request, '该邮箱已被其他用户使用')
        else:
            # 更新用户信息
            user.email = email
            user.bio = bio

            # 处理头像上传
            if 'avatar' in request.FILES:
                user.avatar = request.FILES['avatar']

            user.save()
            messages.success(request, '个人信息更新成功')
            return redirect('user_profile')

    context = {
        'bookshelf_count': bookshelf_count,
        'novel_count': novel_count,
        'days_registered': days_registered,
    }

    return render(request, 'novel/user/profile.html', context)


@login_required
def change_password(request):
    """修改密码视图"""
    user = request.user

    if request.method == 'POST':
        current_password = request.POST.get('current_password')
        new_password = request.POST.get('new_password')
        confirm_password = request.POST.get('confirm_password')

        # 验证当前密码
        if not user.check_password(current_password):
            messages.error(request, '当前密码不正确')
        elif new_password != confirm_password:
            messages.error(request, '两次输入的新密码不一致')
        elif len(new_password) < 6:
            messages.error(request, '密码长度至少为6个字符')
        else:
            # 更新密码
            user.set_password(new_password)
            user.save()

            # 更新会话，避免用户被登出
            update_session_auth_hash(request, user)

            messages.success(request, '密码修改成功')
            return redirect('user_profile')

    # 获取用户书架中的小说数量（用于侧边栏显示）
    bookshelf_count = Bookshelf.objects.filter(user=user).count()

    context = {
        'bookshelf_count': bookshelf_count,
    }

    return render(request, 'novel/user/change_password.html', context)


@login_required
def bookshelf(request):
    """用户书架视图"""
    user = request.user

    # 获取排序方式
    sort_by = request.GET.get('sort', 'updated')

    # 根据排序方式查询书架
    if sort_by == 'added':
        bookshelf_items = Bookshelf.objects.filter(user=user).order_by('-added_at')
    elif sort_by == 'title':
        bookshelf_items = Bookshelf.objects.filter(user=user).order_by('novel__title')
    else:  # 默认按最近阅读排序
        bookshelf_items = Bookshelf.objects.filter(user=user).order_by('-last_read_chapter__updated_at')

    # 为每个书架项目计算阅读进度
    for item in bookshelf_items:
        # 获取小说总章节数
        total_chapters = Chapter.objects.filter(novel=item.novel).count()
        item.total_chapters = total_chapters

        # 如果有最后阅读章节，计算已读章节数和进度
        if item.last_read_chapter:
            read_count = Chapter.objects.filter(
                novel=item.novel,
                order__lte=item.last_read_chapter.order
            ).count()

            item.read_count = read_count

            if total_chapters > 0:
                item.progress_percentage = int((read_count / total_chapters) * 100)
            else:
                item.progress_percentage = 0
        else:
            item.read_count = 0
            item.progress_percentage = 0

    # 分页
    paginator = Paginator(bookshelf_items, 10)  # 每页10项
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    context = {
        'bookshelf_items': page_obj,
        'sort_by': sort_by,
        'is_paginated': page_obj.has_other_pages(),
        'page_obj': page_obj,
    }

    return render(request, 'novel/user/bookshelf.html', context)


@login_required
def author_apply(request):
    """申请成为作者"""
    user = request.user

    # 如果已经是作者，重定向到个人中心
    if user.role != 'reader':
        messages.info(request, '您已经是作者，无需申请')
        return redirect('user_profile')

    # 检查是否有待审核的申请
    pending_application = AuthorApplication.objects.filter(
        user=user,
        status='pending'
    ).first()

    if request.method == 'POST':
        # 如果已有待审核申请，不允许再次提交
        if pending_application:
            messages.error(request, '您已有一个待审核的申请，请耐心等待')
            return redirect('author_apply')

        reason = request.POST.get('reason', '')

        if not reason:
            messages.error(request, '请填写申请理由')
        else:
            # 创建申请
            AuthorApplication.objects.create(
                user=user,
                reason=reason,
                status='pending'
            )

            messages.success(request, '申请已提交，请等待管理员审核')
            return redirect('user_profile')

    context = {
        'pending_application': pending_application,
    }

    return render(request, 'novel/user/author_apply.html', context)


# 小说相关视图
def novel_list(request):
    """小说列表页"""
    # 获取筛选参数
    category_id = request.GET.get('category')
    sort_by = request.GET.get('sort', 'newest')

    # 基本查询：只显示已审核通过的小说
    novels = Novel.objects.filter(status='approved')

    # 分类筛选
    if category_id:
        novels = novels.filter(category_id=category_id)
        current_category = get_object_or_404(Category, id=category_id).name
    else:
        current_category = '全部'

    # 排序
    if sort_by == 'popular':
        # 按收藏数量排序
        novels = novels.annotate(bookshelf_count=Count('in_bookshelves')).order_by('-bookshelf_count')
    elif sort_by == 'updated':
        # 按更新时间排序
        novels = novels.order_by('-updated_at')
    else:  # 默认按创建时间排序
        novels = novels.order_by('-created_at')

    # 获取所有分类
    categories = Category.objects.all()

    # 分页
    paginator = Paginator(novels, 12)  # 每页12本小说
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    context = {
        'novels': page_obj,
        'categories': categories,
        'category_id': category_id,
        'sort_by': sort_by,
        'current_category': current_category,
        'is_paginated': page_obj.has_other_pages(),
        'page_obj': page_obj,
    }

    return render(request, 'novel/novel/list.html', context)


def novel_search(request):
    """小说搜索结果页"""
    query = request.GET.get('q', '')
    category_id = request.GET.get('category')
    sort_by = request.GET.get('sort', 'relevance')

    # 基本查询：只显示已审核通过的小说
    novels = Novel.objects.filter(status='approved')

    # 搜索关键词
    if query:
        novels = novels.filter(
            Q(title__icontains=query) |
            Q(description__icontains=query) |
            Q(author__username__icontains=query)
        )

    # 分类筛选
    if category_id:
        novels = novels.filter(category_id=category_id)

    # 排序
    if sort_by == 'newest':
        novels = novels.order_by('-created_at')
    elif sort_by == 'popular':
        novels = novels.annotate(bookshelf_count=Count('in_bookshelves')).order_by('-bookshelf_count')
    # 默认按相关度排序（简单实现，实际中可能需要更复杂的算法）

    # 获取所有分类
    categories = Category.objects.all()

    # 如果用户已登录，获取其书架中的小说ID列表
    user_bookshelf_novels = []
    if request.user.is_authenticated:
        user_bookshelf_novels = list(
            Bookshelf.objects.filter(user=request.user).values_list('novel_id', flat=True)
        )

    # 分页
    paginator = Paginator(novels, 10)  # 每页10本小说
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    context = {
        'query': query,
        'novels': page_obj,
        'categories': categories,
        'category_id': category_id,
        'sort_by': sort_by,
        'user_bookshelf_novels': user_bookshelf_novels,
        'is_paginated': page_obj.has_other_pages(),
        'page_obj': page_obj,
        'paginator': paginator,
    }

    return render(request, 'novel/novel/search.html', context)


def novel_detail(request, novel_id):
    """小说详情页"""
    # 获取小说信息，确保状态为已审核通过
    novel = get_object_or_404(Novel, id=novel_id, status='approved')

    # 获取小说章节，按顺序排列
    chapters = Chapter.objects.filter(novel=novel).order_by('order')

    # 获取作者的其他作品
    author_novels = Novel.objects.filter(
        author=novel.author,
        status='approved'
    ).exclude(id=novel_id)[:4]

    # 检查小说是否在用户书架中
    is_in_bookshelf = False
    last_read_chapter = None

    if request.user.is_authenticated:
        bookshelf_item = Bookshelf.objects.filter(user=request.user, novel=novel).first()
        if bookshelf_item:
            is_in_bookshelf = True
            last_read_chapter = bookshelf_item.last_read_chapter

    # 增加浏览次数
    # novel.views = novel.views + 1 if novel.views else 1
    # novel.save(update_fields=['views'])

    context = {
        'novel': novel,
        'chapters': chapters,
        'author_novels': author_novels,
        'is_in_bookshelf': is_in_bookshelf,
        'last_read_chapter': last_read_chapter,
    }

    return render(request, 'novel/novel/detail.html', context)


def read_novel(request, novel_id):
    """小说阅读页（重定向到第一章）"""
    novel = get_object_or_404(Novel, id=novel_id, status='approved')

    # 获取第一章
    first_chapter = Chapter.objects.filter(novel=novel).order_by('order').first()

    if first_chapter:
        return redirect('read_chapter', novel_id=novel_id, chapter_id=first_chapter.id)
    else:
        messages.info(request, '该小说暂无章节')
        return redirect('novel_detail', novel_id=novel_id)


def read_chapter(request, novel_id, chapter_id):
    """章节阅读页"""
    novel = get_object_or_404(Novel, id=novel_id, status='approved')
    chapter = get_object_or_404(Chapter, id=chapter_id, novel=novel)

    # 获取上一章和下一章
    prev_chapter = Chapter.objects.filter(
        novel=novel,
        order__lt=chapter.order
    ).order_by('-order').first()

    next_chapter = Chapter.objects.filter(
        novel=novel,
        order__gt=chapter.order
    ).order_by('order').first()

    # 检查小说是否在用户书架中
    is_in_bookshelf = False

    if request.user.is_authenticated:
        # 更新阅读记录
        bookshelf_item, created = Bookshelf.objects.get_or_create(
            user=request.user,
            novel=novel,
            defaults={'last_read_chapter': chapter}
        )

        if not created and bookshelf_item.last_read_chapter != chapter:
            bookshelf_item.last_read_chapter = chapter
            bookshelf_item.save()

        is_in_bookshelf = True

    context = {
        'novel': novel,
        'chapter': chapter,
        'prev_chapter': prev_chapter,
        'next_chapter': next_chapter,
        'is_in_bookshelf': is_in_bookshelf,
    }

    return render(request, 'novel/novel/read.html', context)


# AJAX API视图
@login_required
@require_POST
def add_to_bookshelf(request):
    """添加小说到书架的API"""
    data = request.POST if request.content_type == 'application/x-www-form-urlencoded' else json.loads(request.body)
    novel_id = data.get('novel_id')

    if not novel_id:
        return JsonResponse({"detail": "小说ID不能为空"}, status=400)

    try:
        novel = Novel.objects.get(id=novel_id, status='approved')
    except Novel.DoesNotExist:
        return JsonResponse({"detail": "小说不存在或未通过审核"}, status=404)

    bookshelf, created = Bookshelf.objects.get_or_create(
        user=request.user,
        novel=novel
    )

    if created:
        return JsonResponse({"detail": "已添加到书架"}, status=201)
    else:
        return JsonResponse({"detail": "该小说已在书架中"})


@login_required
@require_POST
def remove_from_bookshelf(request):
    """从书架中移除小说的API"""
    data = request.POST if request.content_type == 'application/x-www-form-urlencoded' else json.loads(request.body)
    novel_id = data.get('novel_id')

    if not novel_id:
        return JsonResponse({"detail": "小说ID不能为空"}, status=400)

    try:
        bookshelf = Bookshelf.objects.get(user=request.user, novel_id=novel_id)
        bookshelf.delete()
        return JsonResponse({"detail": "已从书架中移除"})
    except Bookshelf.DoesNotExist:
        return JsonResponse({"detail": "该小说不在书架中"}, status=404)


@login_required
@require_POST
def update_reading_progress(request, chapter_id):
    """更新阅读进度的API"""
    try:
        chapter = Chapter.objects.get(id=chapter_id)
        novel = chapter.novel

        # 更新书架中的阅读进度
        bookshelf, created = Bookshelf.objects.get_or_create(
            user=request.user,
            novel=novel,
            defaults={'last_read_chapter': chapter}
        )

        if not created and bookshelf.last_read_chapter != chapter:
            bookshelf.last_read_chapter = chapter
            bookshelf.save()

        return JsonResponse({"detail": "阅读进度已更新"})
    except Chapter.DoesNotExist:
        return JsonResponse({"detail": "章节不存在"}, status=404)


# views.py
class PublicNovelListView(generics.ListAPIView):
    queryset = Novel.objects.filter(status='approved')
    serializer_class = NovelSerializer


class AuthorNovelViewSet(viewsets.ModelViewSet):
    """作者专用小说API"""
    serializer_class = NovelCreateSerializer
    permission_classes = [permissions.IsAuthenticated, IsAuthorOwner]

    def get_queryset(self):
        """作者只能看到自己的小说"""
        return Novel.objects.filter(author=self.request.user)

    def perform_create(self, serializer):
        """创建时自动关联作者"""
        serializer.save(author=self.request.user)

    @action(detail=True, methods=['patch'])
    def submit_review(self, request, pk=None):
        """提交/重新提交审核"""
        novel = self.get_object()
        serializer = NovelStatusSerializer(
            novel,
            data={'status': 'pending'},
            partial=True
        )
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response({'status': '已提交审核'})


def author_center_view(request):
    return render(request, 'novel/user/author_center.html')


class CategoryListAPIView(ListAPIView):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer
    # queryset = Novel.objects.all().order_by('id')
    permission_classes = [permissions.AllowAny]

    @method_decorator(cache_page(60 * 5))  # 缓存 5 分钟
    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)

class AuthorWorksViewSet(viewsets.ModelViewSet):
    """
    该视图集用于管理当前作者的所有作品，支持读、创建、修改和删除操作。
    权限要求用户已认证且为作者。
    通过get_queryset方法筛选出当前作者的所有小说。
    根据不同的操作返回不同的序列化器。
    """
    permission_classes = [IsAuthenticated, IsAuthorOwner]

    def get_queryset(self):
        """
        筛选出当前作者的所有小说
        """
        return Novel.objects.filter(author=self.request.user)

    def get_serializer_class(self):
        """
        根据不同的操作返回不同的序列化器
        对于创建操作，使用 NovelCreateSerializer
        其他操作使用 NovelSerializer
        """
        if self.action == 'create':
            return NovelCreateSerializer
        return NovelSerializer

    def perform_create(self, serializer):
        """
        创建小说时自动关联作者
        """
        serializer.save(author=self.request.user)